/*
   mod_antistatus 0.01
   Copyright (C) 2011, En Newman

   All rights reserved.

   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this
      list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   * The names of the contributors may not be used to endorse or promote 
     products derived from this software without specific prior written
     permission.
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_protocol.h"
#include "http_core.h"
#include "http_main.h"
#include "http_log.h"
#include "apr_strings.h"

#define MODULE_NAME "mod_antistatus"
#define MODULE_VERSION "0.01"

module AP_MODULE_DECLARE_DATA antistatus_module;

/* Check a request for presence of server-status handler. */
static int check_serverstatus(request_rec *r)
{
	
    /* Decline to handle subrequests: no infinite loop. */
    if (!ap_is_initial_req(r)) {
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                     "mod_antistatus: SKIPPED: Not initial request");
        return DECLINED;
    }

    /* Determine the handler for this request via subrequest */
    request_rec *subr = ap_sub_req_lookup_uri(r->uri, r, NULL);
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                  "mod_antistatus: found subreq handler: %s", subr->handler);

    if (!subr->handler) {
        return DECLINED;
    }

    /* If the handler is server-status, return 403 forbidden */
    if (strncmp(subr->handler, "server-status", strlen("server-status")) == 0) {
        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
                    "Blocked, no server-status access");
        /* return 403 */
        return HTTP_FORBIDDEN;
    }
    ap_destroy_sub_req(subr);

    /* The handler is not server-status, decline to handle this request */
    return DECLINED;
}

/* Basic access check handler. */
static int antistatus_handler(request_rec *r)
{
    int result;

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
		  "mod_antistatus: Entering normal handler");
    result = check_serverstatus(r);
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
		  "mod_antistatus: Exiting normal handler");
    return result;
}

/* Startup-time initialization. No configs to handle, just print a message */
static int antistatus_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
                 MODULE_NAME " " MODULE_VERSION " started.");
    return OK;
}

static void register_hooks(apr_pool_t *p)
{
    /* print the startup message */
    ap_hook_post_config(antistatus_init, NULL, NULL, APR_HOOK_MIDDLE);
    /* check for a server-status request, deny if present */
    ap_hook_access_checker(antistatus_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA antistatus_module = {
    STANDARD20_MODULE_STUFF,
    NULL,                       /* create per-dir    config structures */
    NULL,                       /* merge  per-dir    config structures */
    NULL,                       /* create per-server config structures */
    NULL,                       /* merge  per-server config structures */
    NULL,                       /* table of config file commands       */
    register_hooks
};
